////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef __WN_MATRIX_33_H__
#define __WN_MATRIX_33_H__

#include "WNCore/inc/WNTypes.h"

namespace WNMath {
    class WNMatrix44;
    class WNQuaternion;
    class WNVector2;
    class WNVector3;

    class WNMatrix33 {
    public:
        WNMatrix33();
        explicit WNMatrix33(const WN_FLOAT32* _f);
        explicit WNMatrix33(const WNVector2& _vector1,
                            const WNVector2& _vector2,
                            const WNVector2& _vector3);
        explicit WNMatrix33(WN_FLOAT32 _m11, WN_FLOAT32 _m12, WN_FLOAT32 _m13,
                            WN_FLOAT32 _m21, WN_FLOAT32 _m22, WN_FLOAT32 _m23,
                            WN_FLOAT32 _m31, WN_FLOAT32 _m32, WN_FLOAT32 _m33);

        operator WN_FLOAT32* ();
        operator const WN_FLOAT32* () const;

        WN_FLOAT32& operator () (WN_INT32 _row, WN_INT32 _column);
        WN_FLOAT32 operator () (WN_INT32 _row, WN_INT32 _column) const;

        WNMatrix33& operator *= (const WNMatrix33& _matrix);
        WNMatrix33& operator += (const WNMatrix33& _matrix);
        WNMatrix33& operator -= (const WNMatrix33& _matrix);
        WNMatrix33& operator *= (WN_FLOAT32 _f);
        WNMatrix33& operator /= (WN_FLOAT32 _f);

        WNMatrix33 operator + () const;
        WNMatrix33 operator - () const;

        WNMatrix33 operator * (const WNMatrix33& _matrix) const;
        WNMatrix33 operator + (const WNMatrix33& _matrix) const;
        WNMatrix33 operator - (const WNMatrix33& _matrix) const;
        WNMatrix33 operator * (WN_FLOAT32 _f) const;
        WNMatrix33 operator / (WN_FLOAT32 _f) const;

        friend WNMatrix33 operator * (WN_FLOAT32 _f, const WNMatrix33& _matrix);
        friend WNMatrix33 operator / (WN_FLOAT32 _f, const WNMatrix33& _matrix);

        WN_BOOL operator == (const WNMatrix33& _matrix) const;
        WN_BOOL operator != (const WNMatrix33& _matrix) const;

        WN_VOID Zero();
        WN_VOID Identity();
        WN_VOID Transpose();
        WN_BOOL Invert();

        WN_FLOAT32 Determinant() const;
        WN_FLOAT32 Trace() const;

        WN_BOOL IsIdentity() const;
        WN_BOOL IsSymmetric() const;
        WN_BOOL IsDiagonal() const;
        WN_BOOL IsRotated() const;

        WN_VOID Set(const WN_FLOAT32* _f);
        WN_VOID Set(WN_FLOAT32 _m11, WN_FLOAT32 _m12, WN_FLOAT32 _m13,
                    WN_FLOAT32 _m21, WN_FLOAT32 _m22, WN_FLOAT32 _m23,
                    WN_FLOAT32 _m31, WN_FLOAT32 _m32, WN_FLOAT32 _m33);
        WN_VOID SetRow(WN_UINT8 _row, const WNVector3& _data);
        WN_VOID SetColumn(WN_UINT8 _column, const WNVector3& _data);

        WNMatrix33 GetTransposed() const;
        WNMatrix33 GetInverted() const;
        WNMatrix33 GetAdjugate() const;
        WNVector3 GetRow(WN_UINT8 _row) const;
        WNVector3 GetColumn(WN_UINT8 _column) const;

    public:
        union {
            struct {
                WN_FLOAT32 _11, _12, _13;
                WN_FLOAT32 _21, _22, _23;
                WN_FLOAT32 _31, _32, _33;
            };

            WN_FLOAT32 raw1D[9];
            WN_FLOAT32 raw2D[3][3];
        };
    };
}

#endif // __WN_MATRIX_33_H__